<template>
  <div class="category-management">
    <div class="header">
      <h2>分类管理</h2>
      <div class="header-actions">
        <button @click="showTreeView = !showTreeView" :class="['btn', 'btn-info', { 'active': showTreeView }]">
          <i class="fas fa-sitemap"></i> {{ showTreeView ? '列表视图' : '树形视图' }}
        </button>
        <button @click="showAddDialog = true" class="btn btn-primary">
          <i class="fas fa-plus"></i> 新增分类
        </button>
      </div>
    </div>

    <!-- 搜索过滤区域 -->
    <div v-if="!showTreeView" class="filter-section">
      <div class="filter-row">
        <div class="filter-item">
          <label>关键词搜索:</label>
          <input
            v-model="searchParams.keyword"
            type="text"
            placeholder="分类名称或标识"
            class="form-input"
            @keyup.enter="loadCategoryList"
          />
        </div>
        <div class="filter-item">
          <label>层级:</label>
          <select v-model="searchParams.level" class="form-select">
            <option value="">全部层级</option>
            <option value="1">一级分类</option>
            <option value="2">二级分类</option>
            <option value="3">三级分类</option>
          </select>
        </div>
        <div class="filter-item">
          <label>状态:</label>
          <select v-model="searchParams.status" class="form-select">
            <option value="">全部状态</option>
            <option value="1">启用</option>
            <option value="0">禁用</option>
          </select>
        </div>
        <div class="filter-actions">
          <button @click="loadCategoryList" class="btn btn-info">
            <i class="fas fa-search"></i> 搜索
          </button>
          <button @click="resetSearch" class="btn btn-secondary">
            <i class="fas fa-redo"></i> 重置
          </button>
        </div>
      </div>
    </div>

    <!-- 树形视图 -->
    <div v-if="showTreeView" class="tree-container">
      <div class="tree-header">
        <h3>分类树形结构</h3>
        <button @click="loadCategoryTree" class="btn btn-sm btn-info">
          <i class="fas fa-refresh"></i> 刷新
        </button>
      </div>
      <div class="tree-content">
        <div v-if="categoryTree.length === 0" class="no-data">暂无分类数据</div>
        <ul v-else class="category-tree">
          <CategoryTreeNode
            v-for="category in categoryTree"
            :key="category.id"
            :category="category"
            @edit="editCategory"
            @delete="deleteCategoryAction"
            @add-child="addChildCategory"
          />
        </ul>
      </div>
    </div>

    <!-- 列表视图 -->
    <div v-else class="table-container">
      <table class="data-table">
        <thead>
          <tr>
            <th>ID</th>
            <th>分类名称</th>
            <th>标识(Slug)</th>
            <th>层级</th>
            <th>路径</th>
            <th>排序</th>
            <th>状态</th>
            <th>叶子节点</th>
            <th>创建时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="category in categoryList" :key="category.id">
            <td>{{ category.id }}</td>
            <td class="category-name">
              <div class="category-info">
                <span class="level-indicator" :style="{ marginLeft: (category.level - 1) * 20 + 'px' }">
                  {{ '└─'.repeat(Math.max(0, category.level - 1)) }}
                </span>
                <strong>{{ category.name }}</strong>
              </div>
            </td>
            <td>{{ category.slug }}</td>
            <td>
              <span class="level-badge">Level {{ category.level }}</span>
            </td>
            <td class="category-path">{{ category.path }}</td>
            <td>{{ category.sortOrder }}</td>
            <td>
              <span :class="['status-badge', category.status === 1 ? 'status-active' : 'status-inactive']">
                {{ category.status === 1 ? '启用' : '禁用' }}
              </span>
            </td>
            <td>
              <span :class="['leaf-badge', category.isLeaf === 1 ? 'is-leaf' : 'has-children']">
                {{ category.isLeaf === 1 ? '是' : '否' }}
              </span>
            </td>
            <td>{{ formatDateTime(category.createdAt) }}</td>
            <td class="actions">
              <button @click="editCategory(category)" class="btn btn-sm btn-warning">
                <i class="fas fa-edit"></i> 编辑
              </button>
              <button @click="addChildCategory(category)" class="btn btn-sm btn-success">
                <i class="fas fa-plus"></i> 添加子类
              </button>
              <button @click="deleteCategoryAction(category)" class="btn btn-sm btn-danger">
                <i class="fas fa-trash"></i> 删除
              </button>
            </td>
          </tr>
          <tr v-if="categoryList.length === 0">
            <td colspan="10" class="no-data">暂无分类数据</td>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- 分页组件 (仅列表视图) -->
    <div v-if="!showTreeView" class="pagination-section">
      <div class="pagination-info">
        共 {{ total }} 条记录
      </div>
      <div class="pagination-controls">
        <button
          @click="changePage(current - 1)"
          :disabled="current <= 1"
          class="btn btn-sm btn-secondary"
        >
          上一页
        </button>
        <span class="page-numbers">
          <button
            v-for="page in getPageNumbers()"
            :key="page"
            @click="changePage(page)"
            :class="['btn', 'btn-sm', page === current ? 'btn-primary' : 'btn-outline']"
          >
            {{ page }}
          </button>
        </span>
        <button
          @click="changePage(current + 1)"
          :disabled="current >= Math.ceil(total / pageSize)"
          class="btn btn-sm btn-secondary"
        >
          下一页
        </button>
      </div>
    </div>

    <!-- 新增/编辑分类弹窗 -->
    <div v-if="showAddDialog || showEditDialog" class="modal-overlay">
      <div class="modal-content" @click.stop>
        <div class="modal-header">
          <h3>{{ showEditDialog ? '编辑分类' : '新增分类' }}</h3>
          <button @click="closeDialog" class="close-btn">&times;</button>
        </div>
        <div class="modal-body">
          <form @submit.prevent="saveCategory">
            <div class="form-row">
              <div class="form-group">
                <label>分类名称 *</label>
                <input v-model="formData.name" type="text" required class="form-input" placeholder="请输入分类名称" />
              </div>
              <div class="form-group">
                <label>标识(Slug)</label>
                <input v-model="formData.slug" type="text" class="form-input" placeholder="留空自动生成" />
              </div>
            </div>
            <div class="form-row">
              <div class="form-group">
                <label>父级分类</label>
                <select v-model="formData.parentId" class="form-select">
                  <option :value="null">顶级分类</option>
                  <option v-for="parent in parentCategories" :key="parent.id" :value="parent.id">
                    {{ parent.name }}
                  </option>
                </select>
              </div>
            </div>
            <div class="form-row">
              <div class="form-group">
                <label>排序值 *</label>
                <input v-model.number="formData.sortOrder" type="number" required class="form-input" placeholder="数字越小排序越靠前" />
              </div>
              <div class="form-group">
                <label>状态</label>
                <select v-model.number="formData.status" class="form-select">
                  <option :value="1">启用</option>
                  <option :value="0">禁用</option>
                </select>
              </div>
            </div>
            <div class="form-actions">
              <button type="button" @click="closeDialog" class="btn btn-secondary">取消</button>
              <button type="submit" :disabled="saving" class="btn btn-primary">
                {{ saving ? '保存中...' : '保存' }}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { getCategoryList, getCategoryTree, createCategory, updateCategory, deleteCategory } from '@/api/category'
import type { Category, CategoryTreeDTO, CategoryQueryParams } from '@/types/category'
import CategoryTreeNode from '@/components/CategoryTreeNode.vue'

// 响应式数据
const showTreeView = ref(true)
const categoryList = ref<Category[]>([])
const categoryTree = ref<CategoryTreeDTO[]>([])
const parentCategories = ref<Category[]>([])
const total = ref(0)
const current = ref(1)
const pageSize = ref(20)
const loading = ref(false)
const saving = ref(false)

// 弹窗状态
const showAddDialog = ref(false)
const showEditDialog = ref(false)
const currentCategory = ref<Category | null>(null)
const parentCategory = ref<Category | null>(null)

// 搜索参数
const searchParams = reactive<CategoryQueryParams>({
  keyword: '',
  level: undefined,
  status: undefined,
  page: 1,
  size: 20
})

// 表单数据
const formData = reactive({
  id: 0,
  name: '',
  slug: '',
  parentId: null as number | null,
  sortOrder: 1,
  status: 1
})

// 计算属性 - 格式化父级分类选项
const formattedParentCategories = computed(() => {
  return parentCategories.value.map(cat => ({
    ...cat,
    displayName: `${'  '.repeat(cat.level - 1)}${cat.name}`
  }))
})

// 加载分类列表
const loadCategoryList = async () => {
  loading.value = true
  try {
    searchParams.page = current.value
    searchParams.size = pageSize.value
    const response = await getCategoryList(searchParams)
    categoryList.value = response.data.list
    total.value = response.data.total
  } catch (error) {
    console.error('加载分类列表失败:', error)
    alert('加载分类列表失败')
  } finally {
    loading.value = false
  }
}

// 加载分类树
const loadCategoryTree = async () => {
  loading.value = true
  try {
    const response = await getCategoryTree()
    categoryTree.value = response.data
  } catch (error) {
    console.error('加载分类树失败:', error)
    alert('加载分类树失败')
  } finally {
    loading.value = false
  }
}

// 加载父级分类选项
const loadParentCategories = async () => {
  try {
    const response = await getCategoryList({ page: 1, size: 1000 })
    parentCategories.value = response.data.list
  } catch (error) {
    console.error('加载父级分类失败:', error)
  }
}

// 重置搜索
const resetSearch = () => {
  searchParams.keyword = ''
  searchParams.level = undefined
  searchParams.status = undefined
  current.value = 1
  loadCategoryList()
}

// 分页切换
const changePage = (page: number) => {
  if (page < 1 || page > Math.ceil(total.value / pageSize.value)) return
  current.value = page
  loadCategoryList()
}

// 获取分页数字
const getPageNumbers = () => {
  const nums: number[] = []
  const totalPages = Math.ceil(total.value / pageSize.value)
  const start = Math.max(1, current.value - 2)
  const end = Math.min(totalPages, current.value + 2)
  
  for (let i = start; i <= end; i++) {
    nums.push(i)
  }
  return nums
}

// 编辑分类
const editCategory = (category: Category) => {
  currentCategory.value = category
  Object.assign(formData, {
    id: category.id,
    name: category.name,
    slug: category.slug,
    parentId: category.parentId || null,
    sortOrder: category.sortOrder,
    status: category.status
  })
  showEditDialog.value = true
}

// 添加子分类
const addChildCategory = (parent: Category) => {
  parentCategory.value = parent
  Object.assign(formData, {
    id: 0,
    name: '',
    slug: '',
    parentId: parent.id,
    sortOrder: 1,
    status: 1
  })
  showAddDialog.value = true
}

// 删除分类
const deleteCategoryAction = async (category: Category) => {
  if (!confirm(`确定要删除分类"${category.name}"吗？`)) return
  
  try {
    await deleteCategory(category.id)
    alert('删除成功')
    if (showTreeView.value) {
      loadCategoryTree()
    } else {
      loadCategoryList()
    }
  } catch (error) {
    console.error('删除分类失败:', error)
    alert('删除分类失败')
  }
}

// 保存分类
const saveCategory = async () => {
  saving.value = true
  try {
    const categoryData = {
      name: formData.name,
      slug: formData.slug,
      parentId: formData.parentId,
      sortOrder: formData.sortOrder,
      status: formData.status
    } as any

    if (showEditDialog.value && currentCategory.value) {
      await updateCategory(currentCategory.value.id, categoryData)
      alert('更新成功')
    } else {
      await createCategory(categoryData)
      alert('创建成功')
    }
    
    closeDialog()
    if (showTreeView.value) {
      loadCategoryTree()
    } else {
      loadCategoryList()
    }
    loadParentCategories()
  } catch (error) {
    console.error('保存分类失败:', error)
    alert('保存分类失败')
  } finally {
    saving.value = false
  }
}

// 关闭弹窗
const closeDialog = () => {
  showAddDialog.value = false
  showEditDialog.value = false
  currentCategory.value = null
  parentCategory.value = null
  Object.assign(formData, {
    id: 0,
    name: '',
    slug: '',
    parentId: null,
    sortOrder: 1,
    status: 1
  })
}

// 格式化日期时间
const formatDateTime = (dateStr: string) => {
  return new Date(dateStr).toLocaleString('zh-CN')
}

// 页面加载时获取数据
onMounted(() => {
  loadCategoryTree()
  loadCategoryList()  // 添加列表数据加载
  loadParentCategories()
})
</script>



<style scoped>
.category-management {
  padding: 20px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.header h2 {
  margin: 0;
  color: #333;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.filter-section {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.filter-row {
  display: flex;
  gap: 20px;
  align-items: end;
  flex-wrap: wrap;
}

.filter-item {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.filter-item label {
  font-weight: 500;
  color: #555;
}

.form-input, .form-select {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.tree-container {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.tree-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #dee2e6;
}

.tree-content {
  max-height: 600px;
  overflow-y: auto;
}

.category-tree {
  list-style: none;
  padding: 0;
  margin: 0;
}

.tree-node {
  margin-bottom: 5px;
}

.tree-node-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
  border: 1px solid #e9ecef;
}

.tree-node-info {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
}

.tree-toggle {
  cursor: pointer;
  width: 16px;
  text-align: center;
  color: #666;
}

.tree-toggle-empty {
  width: 16px;
}

.category-name {
  font-weight: 500;
  color: #333;
}

.category-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  margin-right: 10px;
}

.category-slug {
  color: #666;
  font-size: 12px;
}

.tree-node-actions {
  display: flex;
  gap: 5px;
}

.tree-children {
  list-style: none;
  padding-left: 30px;
  margin-top: 5px;
}

.table-container {
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th {
  background: #f8f9fa;
  padding: 12px 8px;
  text-align: left;
  font-weight: 600;
  border-bottom: 2px solid #dee2e6;
}

.data-table td {
  padding: 12px 8px;
  border-bottom: 1px solid #dee2e6;
  vertical-align: middle;
}

.level-indicator {
  color: #999;
  margin-right: 5px;
}

.level-badge {
  background: #e9ecef;
  color: #495057;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 11px;
}

.category-path {
  font-family: monospace;
  font-size: 12px;
  color: #666;
}

.status-badge {
  padding: 4px 8px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.status-active {
  background: #d4edda;
  color: #155724;
}

.status-inactive {
  background: #f8d7da;
  color: #721c24;
}

.leaf-badge {
  padding: 2px 6px;
  border-radius: 8px;
  font-size: 11px;
}

.is-leaf {
  background: #d1ecf1;
  color: #0c5460;
}

.has-children {
  background: #fff3cd;
  color: #856404;
}

.actions .btn {
  margin-right: 5px;
  margin-bottom: 5px;
}

.btn {
  padding: 8px 12px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: all 0.2s;
}

.btn-sm {
  padding: 4px 8px;
  font-size: 11px;
}

.btn-primary {
  background: #007bff;
  color: white;
}

.btn-info {
  background: #17a2b8;
  color: white;
}

.btn-info.active {
  background: #138496;
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn-warning {
  background: #ffc107;
  color: #212529;
}

.btn-success {
  background: #28a745;
  color: white;
}

.btn-danger {
  background: #dc3545;
  color: white;
}

.btn-outline {
  background: transparent;
  border: 1px solid #ddd;
  color: #333;
}

.pagination-section {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.page-numbers {
  display: flex;
  gap: 5px;
}

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.modal-content {
  background: #ffffff;
  border-radius: 4px;
  width: 90%;
  max-width: 600px;
  max-height: 90vh;
  overflow-y: auto;
  border: 1px solid #e8e8e8;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
  background: #fafafa;
}

.modal-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  color: #333333;
}

.close-btn {
  background: none;
  border: none;
  font-size: 18px;
  cursor: pointer;
  color: #999999;
  padding: 4px;
  line-height: 1;
  transition: color 0.2s;
}

.close-btn:hover {
  color: #666666;
}

.modal-body {
  padding: 20px;
  background: #ffffff;
}

.form-row {
  display: flex;
  gap: 20px;
  margin-bottom: 18px;
}

.form-group {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-group label {
  font-weight: 400;
  color: #666666;
  font-size: 14px;
}

.form-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid #f0f0f0;
}

.no-data {
  text-align: center;
  color: #666;
  font-style: italic;
  padding: 40px;
}
</style> 